Release 10.1A: OpenEdge Development:
Progress 4GL Handbook


Using a persistent procedure as a run-time library

The example in the previous section points to the first major use for persistent procedures. When you learned about internal procedures in Chapter 2, "Using Basic 4GL Constructs," the examples all involved running an internal procedure from elsewhere in the same main procedure file (external procedure). But internal procedures are such a useful thing that you will want to run them from many different places. The only way to run an internal procedure that isn’t local to the caller is with a persistent procedure. In this way, running an internal procedure defined in some other procedure file is a two-step process:

  1. Run the procedure file that contains it as a persistent procedure, or alternatively, to obtain the handle of an instance of the procedure that’s already running.
  2. Run the internal procedure in that handle, using this syntax:
  3. RUN internal-proc IN proc-handle [ ( parameters ) ]. 
    

    If the internal procedure has parameters, you pass them in the usual way.

This allows you to think of a persistent procedure as a library of useful routines you want to be able to run from anywhere in your application. Because the rigid top-down hierarchy of the older application is gone, your application code can run any entry point in any running procedure instance from anywhere in the application. This greatly increases the flexibility of your application and its logic flow.

Obtaining a procedure handle for a persistent procedure

This should lead you to think about how you can make procedure handles available throughout your application. Clearly, the procedure that instantiates the persistent procedure can get its handle back easily with the SET phrase on the RUN statement. But your procedures can be more useful if their handles are more widely available.

Using the SESSION handle to locate running procedures

There is a very useful built-in handle available globally in your application and, among other advantages, is one way to identify all running persistent procedures. This is the SESSION handle. The SESSION handle has many attributes and methods, all of which you can learn about in the online help. You can also see a list of all SESSION attributes by accessing the Session Attributes tool from the PRO*Tools palette, as shown in Figure 13–5.

Figure 13–5: PRO*Tools palette with Session icon selected

Figure 13–6 shows the Session Attributes tool.

Figure 13–6: Session Attributes PRO*Tool

Some of these attributes have readable values that are meaningful to you when you look at them as a list. However, handles are not useful just as numbers (such as the FIRST-CHILD handle value, shown in Figure 13–6).

Your application, however, can make good use of these handles. If you want to examine a list of all running persistent procedures, you start with the SESSION:FIRST-PROCEDURE attribute. This attribute evaluates to the procedure handle of the first of a list of all running procedures. Note that there is no predictable sequence to the procedures in the list. All you can do is scan the list if you need to search for a procedure you’re interested in. From here, you can walk through a sequence of all procedures using the NEXT-SIBLING attribute, which also returns a procedure handle, or with the PREV-SIBLING attribute if you want to walk backwards through the list. The last procedure in the list is available using the LAST-PROCEDURE attribute.

Here’s a very simple example. h-FindUseful.p runs another procedure, h-UsefulProc.p, persistent. Then it searches the session’s procedure list for an internal procedure it wants to run:

/* h-FindUseful.p -- searches for a persistent procedure with a useful 
   routine to run. */ 
DEFINE VARIABLE hUseful AS HANDLE     NO-UNDO. 
RUN h-UsefulProc.p PERSISTENT SET hUseful. 
DEFINE VARIABLE hProc AS HANDLE     NO-UNDO. 
hProc = SESSION:FIRST-PROCEDURE. 
DO WHILE VALID-HANDLE(hProc): 
    IF LOOKUP ("UsefulRoutine1", hProc:INTERNAL-ENTRIES) NE 0 THEN 
    DO: 
        RUN UsefulRoutine1 IN hProc. 
        LEAVE. 
    END. 
    hProc = hProc:NEXT-SIBLING. 
END. 
DELETE PROCEDURE hUseful. 

In a more realistic example, of course, the same procedure that started h-UsefulProc.p would not be the one searching for it. h-UsefulProc.p defines some internal procedures that other procedures in the session would like to run:

/* h-UsefulProc.p -- has an internal procedure others want to find. */ 
PROCEDURE UsefulRoutine1: 
    MESSAGE "It would be useful if you ran this." 
        VIEW-AS ALERT-BOX. 
END PROCEDURE. 
PROCEDURE UsefulRoutine2: 
    MESSAGE "This would be useful too." 
        VIEW-AS ALERT-BOX. 
END PROCEDURE. 

When you run h-FindUseful.p, it locates the running instance of h-UsefulProc.p by looking at every procedure’s INTERNAL-ENTRIES attribute, and runs the routine it’s looking for, as shown in Figure 13–7.

Figure 13–7: h-UsefulProc.p message


Copyright © 2005 Progress Software Corporation
www.progress.com
Voice: (781) 280-4000
Fax: (781) 280-4095